iT邦幫忙

2025 iThome 鐵人賽

DAY 29
0

藍綠佈署

故事

Lala:這次我們的API產品,準備要升級了,是不是應該要通知所有的consumer,告訴他們在過版日的晚上八點可能會有服務的中斷,請他們暫時先不要使用API。

Aries:每次在過版日時,都會非常的忐忑,原因是即使在UAT環境完整驗證過,但還是不能保證在正式環境中,所有服務內所需參數,在該環境中都已經被正確設定完成。

Lala:所以公告可能要說明會停機2小時,如此才可以在那2小時,確定各個服務狀態是否正常。如果異常至少還有2小時可以排查錯誤,最糟狀況就是退回版本。

Sam:其實....應該可以做到藍綠佈署喔!我們想像一個場景,如果在過版日前24小時,新版本的服務已經被佈署到正式環境。但consumer的流量並不會被導入,僅有公司內的我們可以透過特殊的方式驗證是否服務正確。如果異常,因為已經提早了24小時,相關排錯與申請作業就可以從容地進行,這樣勢必也可以大幅提高過版成功率!

Lala:可以這樣做!?是透過kong嗎?

Sam:沒錯,這個點子在我腦中大致上已經成形,就讓我來說明細節吧!

筆者以前在VMWare中,Windows 作業系統下的IIS服務器,佈署dotnet的網頁時,常常在思考要如何做到藍綠佈署或是金絲雀佈署。但過去傳統單體式服務,基本上就是透過Layer 4 Switch協助對多台做Network Load Balancer,除非與網管協同合作,不然很難做到佈署策略的實現。

不過這次系列文是基於容器實踐的,因此在系列文的最後兩天,筆者決定透過kong來完成藍綠佈署的任務,幾個目標希望達成。

  1. 將新版本佈署至環境中,但不影響原有版本的運行。
  2. 透過kong做到同一入口(host/port/path皆相同),仰賴預定義好的header進行分流。
  3. 驗證完新版本確認沒問題後,一樣透過IaC的形式進行版本的置換,盡可能讓服務中斷時間縮短。

事不宜遲,馬上開始進行。

設定

API 的重新版本定義

這次的範本檔在 ironman2025\case_ELK_JPG_Route_Blue_Green 中,請讀者可以移駕到該目錄下,讓筆者逐步說明操作細節。

首先先到2.api_provider目錄下,這次先執行docker build,指令如下:

# 這次將舊版本指定版本號碼1.0.0,新版本則為1.0.1。

docker build -t case_elk_jpg_authzn_weather:1.0.0 .\2.api_provider\case_ELK_JPG_AuthZN_weather
docker build -t case_elk_jpg_authzn_weather:1.0.1 .\2.api_provider\case_ELK_JPG_AuthZN_weather_new_version

上面指令可以看到,筆者將兩個資料夾分別建立了image,目錄與說明簡述如下:

.
├── 2.api_provider/
│    ├─── case_ELK_JPG_AuthZN_weather              #版本:1.0.0
│    └─── case_ELK_JPG_AuthZN_weather_new_version  #版本:1.0.1

實務上其實不會這樣區分,應該會使用git的tag來區分release的docker 版本號。不過為了示範,因此筆者就直接拆分成兩個部分。新的版本僅有新增了幾種僅有外太空才會有的惡劣天氣類型,用來示意這是新版本的更新,新增的部分如下:

// case_ELK_JPG_AuthZN_weather_new_version\Program.cs
var weatherConditions = new[]
{
    "Rainy", "Sunny", "Foggy", "Cloudy", "Thunderstorm", "Sandstorm", "Tornado",
    "Meteor Shower", "Firestorm", "Solar Storm",  # 新增了隕石雨、火風暴、太陽風暴
    "Magnetic Storm", "Ice Storm", "Acid Rain"    # 新增了磁暴、冰風暴以及酸雨
};

docker compose 的重新定義

接下來,關注到docker-compose.yaml中,將這次有異動的部分列出如下:

  case_elk_jpg_authzn_weather:
    image: case_elk_jpg_authzn_weather:1.0.0
    container_name: case_elk_jpg_authzn_weather
    networks:
      - kong-net
    expose:
      - "8080"
    # 若有 volume/logs 需求可加下方設定
    volumes:
      - ./2.api_provider/case_ELK_JPG_AuthZN_weather/logs:/app/logs
    depends_on:
      - opentelemetry-collector

  case_elk_jpg_authzn_weather_blue:
    image: case_elk_jpg_authzn_weather:1.0.1
    ...下同略...

可以看到,在docker compose的專案中,分別為了兩個版本的image建立了服務,因此整個專案新舊版本API服務的示意,就如圖29-1:

新版本尚未建立路由
圖29-1 新版本尚未建立路由

圖29-1就可以看出,雖說已經將新版本定義到docker compose中,但由於kong還沒有設定變更原有的policy,因此原有的consumer還不會受到影響,持續可以存取1.0.0版本的服務(因此不會受到外太空才有的惡劣天氣影響)。

kong 的重新定義

接著為了建立新版本的服務與路由,以實現正式佈署前的預先驗證,就進入到kong.yml的設定,新增了下面的部分

- name: case_ELK_JPG_AuthZN_weather_blue
  url: http://case_ELK_JPG_AuthZN_weather_blue:8080
  routes:
  - name: case_ELK_JPG_AuthZN_weather_blue
    paths:
    - /weather/
    headers: 
      x-version: 
        - blue
    plugins:
    - name: key-auth
      config:
        key_names:
        - apikey
        hide_credentials: false
    - name: acl
      config:
        allow:
        - VIP
        deny: null
        hide_groups_header: false
      enabled: true
      protocols:
      - grpc
      - grpcs
      - http
      - https
      tags:
      - VIP 
- name: case_ELK_JPG_AuthZN_weather
  url: http://case_ELK_JPG_AuthZN_weather:8080
  routes:
  - name: case_ELK_JPG_AuthZN_weather
    paths:
    - /weather/
  ...下同略... 

新的服務指向了http://case_ELK_JPG_AuthZN_weather_blue:8080,這在預期內。另外請特別注意到新route的設定中,path的設定與原有case_ELK_JPG_AuthZN_weatherpaths都一樣是weather,這就表示consumer API 請求的url並不會不同。但有一段細節設定讀者可以注意一下,節錄如下:

    headers: 
      x-version: 
        - blue

這段內容表示,當請求內容帶入了header x-version:bluekong會將進來的流量導入到新的服務,而實現了同一個請求的url,可以根據header內容將流量導到新增的服務中。知道了原理後,就可以進行實驗了。

實驗

1.0.0版本
圖29-2 1.0.0版本

1.0.1版本
圖29-3 1.0.1版本

筆者在上面做了兩個實驗,圖29-2可以看到,consumer可以繼續對http://localhost:8000/weather/yyyy-MM-dd發動請求,附上驗證方式,就可以持續與原有的API進行互動。

而圖29-3 則可以看到,內部資訊單位的測試人員可以使用帶有特殊header(x-version:blue)進行請求,即可針對即將發布的API預先進行驗證。

kibana的紀錄
圖29-4 kibana的紀錄

從圖29-4中也可以看出,kibana記錄了帶有不同header的請求,被成功的導入了不同的route。這種方式可以讓內部資訊人員針對即將要發布的版本,預先佈署到正式環境中確認,確認經過一定的測試後,再決定是否要佈署到正式環境。如此便能預先確認一切是否都準備就緒,而可以避免將過版成敗賭在公告過版的那一瞬間,便可從容地完成過版作業。

新版本導流示意圖
圖29-5 新版本導流示意圖

概念上,在這種設計思維為前提,就可以協助組織完成藍綠佈署,進而提高變更管理的成功率。

小結

筆者在思考藍綠佈署用於kong的場景中,不斷在地思考要如何降低變更管理的成本。原本的想法是,在驗證完成之後,要從kong的角度進行流量的切換,之後再將新建立起來的服務關閉(節省成本)。因為既然服務已經被建立完成,直接切換過去最為妥適。

不過深思了一陣之後,認為這樣涉及到兩個角色的人員作業,分別是公司中的版本更新作業人員(如:operator),以及kong的管理人員(可能是infra人員)。

如果一個版本變更需要涉及到多個角色,其實就表示變更管理所需要的作業流程較為複雜。因此筆者決定在pipeline的設計中,透過docker compose 的指令進行版本變換的操作。而kongblue route,則被留在原地作為變更管理的慣例。

這表示,未來只要變更管理準備版更前,blue route將成為慣例的存在,用來作為預檢查使用。

接下來則是迎來鐵人賽的最後一天,筆者將透過azure pipeline將這段藍綠佈署的變更管理實踐,就讓我們明天見。


上一篇
Day 28 : Kong 的 JWT 實踐 - 認證實作及探索OIDC的流程
下一篇
Day 30 : 透過 Azure DevOps 實踐 Kong 的藍綠佈署 - 2 (鐵人完賽)
系列文
解鎖API超能力:我的30天Kong可觀測性與管理實戰之旅30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言